<?php


namespace app\common\wechat;
use app\common\wechat\WechatConfig;
use think\App;

/**
 *微信支付
 * Class WeChat
 * @package app\api\common
 */
class WechatPay extends WechatConfig
{
    protected $sysConfig;

    public function __construct(App $app)
    {
        parent::__construct($app);
    }


    /**
     * 微信支付统一下单
     * $channel 通道 mini：小程序，account：微信公众号，H5：微信外部浏览器
     * body 订单标题
     */
    public function pay($post,$channel='mini',$body='订单标题'){
        //获取openid
        $openid=$post['openid']??'';
        if(empty($openid))
        {   //用code获取openid
            return ['code'=>0,'msg'=>'openid错误'];
        }
        $ready=$this->get_pay_ready($channel);
        $mch_id=$this->mchid;
        $trade_type=$ready['trade_type'];
        $apKey=$ready['app_secret'];
        $fee = $post['fee']?? 0.01;//举例支付0.01
        $appid = $ready['appid'];
        $nonce_str =$this->nonce_str();//随机字符串
        $out_trade_no = $this->order_number();//商户订单号
        $spbill_create_ip = '127.0.0.1';//服务器的ip【自己填写】;
        $total_fee =   $fee*100;// 微信支付单位是分，所以这里需要*100
        $notify_url= $this->notify_url;


        //这里是按照顺序的 因为下面的签名是按照顺序 排序错误 肯定出错
        $post['appid'] = $appid;
        $post['body'] = $body;
        $post['mch_id'] = $mch_id;
        $post['nonce_str'] = $nonce_str;//随机字符串
        $post['notify_url'] = $notify_url;
        $post['openid'] = $openid;
        $post['out_trade_no'] = $out_trade_no;
        $post['spbill_create_ip'] = $spbill_create_ip;//终端的ip
        $post['total_fee'] = $total_fee;//总金额
        $post['trade_type'] = $trade_type;
        $sign = $this->sign($post,$apKey);//签名
        $post_xml = '<xml>
           <appid>'.$appid.'</appid>
           <body>'.$body.'</body>
           <mch_id>'.$mch_id.'</mch_id>
           <nonce_str>'.$nonce_str.'</nonce_str>
           <notify_url>'.$notify_url.'</notify_url>
           <openid>'.$openid.'</openid>
           <out_trade_no>'.$out_trade_no.'</out_trade_no>
           <spbill_create_ip>'.$spbill_create_ip.'</spbill_create_ip>
           <total_fee>'.$total_fee.'</total_fee>
           <trade_type>'.$trade_type.'</trade_type>
           <sign>'.$sign.'</sign>
        </xml> ';



        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $xml = $this->httpRequest($url,$post_xml,'POST');
        $obj = simplexml_load_string($xml,"SimpleXMLElement", LIBXML_NOCDATA);
        $array = json_decode(json_encode($obj),true);


        if($array['return_code'] == 'SUCCESS' && $array['return_code'] == 'SUCCESS'){
            $time = time();
            $tmp=[];//临时数组用于签名
            $tmp['appId'] = $appid;
            $tmp['nonceStr'] = $nonce_str;
            $tmp['package'] = 'prepay_id='.$array['prepay_id'];
            $tmp['signType'] = 'MD5';
            $tmp['timeStamp'] = "$time";
            $sign_two=$this->sign($tmp,$apKey);
            $data['appId']=$appid;
            $data['state'] = 200;
            $data['timeStamp'] =$time.'';//时间戳
            $data['nonceStr'] = $nonce_str;//随机字符串
            $data['signType'] = 'MD5';//签名算法，暂支持 MD5
            $data['package'] = 'prepay_id='.$array['prepay_id'];//统一下单接口返回的 prepay_id 参数值，提交格式如：prepay_id=*
            $data['paySign'] = $sign_two;//签名,具体签名方案参见微信公众号支付帮助文档;
            $data['out_trade_no'] = $out_trade_no;
            $data['openid']=$openid;
            $data['return_code']='SUCCESS';
            if($trade_type=='MWEB'){
                $data['mweb_url']=$array['mweb_url'];
            }
        }else{
            $data['state'] = 0;
            $data['return_msg'] = $array['return_msg'];
            return ['code'=>0,'msg'=>$data['return_msg']];
        }






        return ['code'=>1,'msg'=>'请求成功','data'=>$data];
    }




    //随机32位字符串
    private function nonce_str(){
        $result = '';
        $str = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';
        for ($i=0;$i<32;$i++){
            $result .= $str[rand(0,48)];
        }
        return $result;
    }



//生成订单号
    private function order_number(){
        return date('Ymd',time()).time().rand(10,99);//18位
    }



//签名 $data要先排好顺序
    private function sign($data,$apKey){
        ksort($data);
        unset($data['fee']);
        $stringA = '';
        foreach ($data as $key=>$value){
            if(!$value) continue;
            if($stringA) $stringA .= '&'.$key."=".$value;
            else $stringA = $key."=".$value;
        }
        $wx_key=$apKey;
        $stringSignTemp = $stringA.'&key='.$wx_key;


        return strtoupper(md5($stringSignTemp));
    }







//获取xml
    private function xml($xml){
        $p = xml_parser_create();
        xml_parse_into_struct($p, $xml, $vals, $index);
        xml_parser_free($p);
        $data = "";
        foreach ($index as $key=>$value) {
            if($key == 'xml' || $key == 'XML') continue;
            $tag = $vals[$value[0]]['tag'];
            $value = $vals[$value[0]]['value'];
            $data[$tag] = $value;
        }
        return $data;
    }


    //不同通道获取对应配置
    protected function get_pay_ready($type){
        $ready=[];
        $ready['mini']=['appid'=>$this->appid,'app_secret'=>$this->app_secret,'trade_type'=>'JSAPI'];
        $ready['account']=['appid'=>$this->wx_appid,'app_secret'=>$this->wx_apk,'trade_type'=>'JSAPI'];
        $ready['h5']=['appid'=>$this->wx_appid,'app_secret'=>$this->wx_apk,'trade_type'=>'MWEB'];
        return $ready[$type];
    }









}